package com.xu.cloud.common.mp;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.apache.ibatis.annotations.Param;

import java.io.Serializable;
import java.util.List;
import java.util.Objects;

/**
 * BaseMapper expand
 *
 * @author xuguan
 * @since 2025/4/17
 */
public interface BaseMapperV2<T> extends BaseMapper<T> {

    /**
     * 根据 whereEntity 条件, 查询第一条记录
     *
     * @param queryWrapper 实体对象封装操作类（可以为 null）
     */
    default T selectFirst(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper) {
        List<T> list = this.selectList(queryWrapper);
        if (list.size() >= 1) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据 ID 新增或修改
     */
    default int insertOrUpdateById(@Param(Constants.ENTITY) T entity) {
        if (Objects.isNull(entity)) {
            return 0;
        }
        final TableInfo tableInfo = TableInfoHelper.getTableInfo(entity.getClass());
        Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
        String keyProperty = tableInfo.getKeyProperty();
        Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
        Object idVal = tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty());
        return !StringUtils.checkValNull(idVal) && Objects.nonNull(this.selectById((Serializable) idVal)) ? this.updateById(entity) : this.insert(entity);
    }

    /**
     * 根据 whereEntity 条件, 新增或修改
     */
    default int insertOrUpdate(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper) {
        if (Objects.isNull(entity)) {
            return 0;
        }
        final int update = this.update(entity, updateWrapper);
        if (update > 0) {
            return update;
        } else {
            return this.insert(entity);
        }
    }
}
